<template>
  <div ref="cesiumContainer" class="cesium-container">
    <div id="credit" class="credit"></div>
    <div class="toolbox" v-show="cesiumInitialized">
      <el-switch v-model="showPaths" active-action-icon="View" inactive-action-icon="Hide" active-text="显示轨迹" />
      <el-switch v-model="showLabels" active-action-icon="View" inactive-action-icon="Hide" active-text="显示名称" />
      <!-- <el-switch v-model="trackEntity" active-action-icon="View" inactive-action-icon="Hide" active-text="视角跟随" /> -->
      <el-switch
        v-model="store.showSatelliteList"
        active-action-icon="View"
        inactive-action-icon="Hide"
        active-text="卫星列表"
        @change="store.toggleShowSatelliteList"
      />
      <el-switch
        v-model="store.showImportList"
        active-action-icon="View"
        inactive-action-icon="Hide"
        active-text="关注卫星"
        @change="store.toggleShowImportList"
      />
    </div>
    <div class="timeline-panel" id="timeline-panel" v-show="cesiumInitialized">
      <div class="timeline-controls">
        <button class="timeline-btn active" id="btn-play-pause" @click="togglePlayPause" title="播放/暂停">
          <span id="play-pause-icon">{{ isPlaying ? '⏸️' : '▶️' }}</span>
        </button>
        <button class="timeline-btn" id="btn-rewind" @click="rewindTime" title="后退10秒">⏪</button>
        <button class="timeline-btn" id="btn-forward" @click="forwardTime" title="前进10秒">⏩</button>
        <button class="timeline-btn" id="btn-slow" @click="decreaseSpeed" title="减速">🐌</button>
        <button class="timeline-btn" id="btn-fast" @click="increaseSpeed" title="加速">🚀</button>
      </div>
    </div>
    <transition name="slide">
      <div id="satPanel" class="sat-panel" v-show="store.showSatelliteMsgBox">
        <span class="close-btn" @click="closePanel">✖</span>
        <div class="sat-Content">
          <div>
            <span> 卫星名称：{{ store.selectedSatellite?.name_en ?? '' }} </span>
            <el-button type="primary" size="small" plain round @click="threatAnalysis" v-show="store.activedTaskId"
              >威胁度分析</el-button
            >
          </div>
          <div>制造国家：{{ store.selectedSatellite?.country ?? '' }}</div>
          <div>卫星类型：{{ store.selectedSatellite?.sat_type ?? '' }}</div>
          <div class="desc">
            {{ store.selectedSatellite?.description }}
          </div>
        </div>
      </div>
    </transition>
  </div>
</template>
<script setup lang="ts">
import { onMounted, ref, useTemplateRef } from 'vue'
import * as Cesium from 'cesium'
import { getSatelliteDetail, getSatelliteTLEData, getTLEDataByTaskId } from '@/api/dashboard'
import * as satellitejs from 'satellite.js'
import { useLayoutStore } from '@/store/modules/layout'
import { getOrbitNumStatus, getOrbitNumType, getPayloadNumStatus } from '@/utils/func/satellite'
const store = useLayoutStore()
const showLabels = ref(true) // 默认显示卫星名称
const showPaths = ref(false) // 默认不显示卫星轨迹
const trackEntity = ref(false)
const MATERIAL_URL = import.meta.env.VITE_MATERIAL_URL
const cesiumContainer = useTemplateRef('cesiumContainer')
interface Emits {
  (e: 'threatAnalysis'): void
}
const emit = defineEmits<Emits>()
const threatAnalysis = () => {
  emit('threatAnalysis')
}

let viewer: Cesium.Viewer
// cesium 是否加载完成
const cesiumInitialized = ref(false)
const initViewer = () => {
  if (cesiumContainer.value) {
    // 创建 Cesium Viewer 实例并禁用不需要的默认控件
    viewer = new Cesium.Viewer(cesiumContainer.value, {
      scene3DOnly: false, // 启用 3D/2D 切换（这里允许 3D 模式）
      geocoder: false, // 关闭位置搜索控件
      homeButton: false, // 关闭回到默认视角按钮
      sceneModePicker: false, // 关闭视图模式切换器
      navigationHelpButton: false, // 关闭帮助按钮
      animation: false, // 关闭默认动画控件
      timeline: false, // 关闭默认时间轴控件（我们使用自定义时间轴）
      creditContainer: 'credit', // 版权信息容器
      fullscreenButton: false, // 关闭全屏按钮
      baseLayerPicker: false, // 关闭底图选择器
      baseLayer: false, // 不使用默认底图
      infoBox: false, // 关掉默认 InfoBox
    })

    // 添加切片影像图层（自定义瓦片服务器）
    viewer.imageryLayers.addImageryProvider(
      new Cesium.UrlTemplateImageryProvider({
        url: `${MATERIAL_URL}/tomcat/saveFile/{z}/{x}/{y}.png`, // 瓦片 URL 模板
        // url: `/assets/material/earth/saveFile/{z}/{x}/{y}.png`, // 瓦片 URL 模板`
        credit: 'credit', // 版权信息
      })
    )
    // 设置相机飞到中国上空 10 万米高度
    const position = Cesium.Cartesian3.fromDegrees(104.0, 35.0, 5000000) // 经度、纬度、高度（单位：米）
    viewer.camera.setView({
      destination: position,
      orientation: {
        heading: 0.0, // 方向
        pitch: -Cesium.Math.PI_OVER_TWO, // 俯仰角
        roll: 0.0, // 横滚角
      },
    })

    // 添加大气层效果
    viewer.scene.globe.enableLighting = false
    viewer.scene.globe.atmosphereBrightnessShift = 0.1
    viewer.scene.globe.atmosphereHueShift = 0.0
    viewer.scene.globe.atmosphereSaturationShift = 0.0

    // 设置时间系统
    const startTime = Cesium.JulianDate.fromDate(new Date())
    const stopTime = Cesium.JulianDate.addSeconds(startTime, 86400, new Cesium.JulianDate()) // 24小时

    viewer.clock.startTime = startTime.clone()
    viewer.clock.stopTime = stopTime.clone()
    viewer.clock.currentTime = startTime.clone()
    viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP
    viewer.clock.multiplier = 1.0

    // 初始化时间轴控制
    initializeTimelineControls()
    // 监控鼠标点击事件
    listenClickEvents()
  }
}

// 时间轴控制功能
const initializeTimelineControls = () => {
  if (!viewer) return

  // 更新时间显示
  viewer.clock.onTick.addEventListener((clock) => {
    const currentTime = clock.currentTime
    const date = Cesium.JulianDate.toDate(currentTime)
    currentTimeDisplay.value = date.toISOString().replace('T', ' ').slice(0, 19) + ' UTC'

    // 更新滑块位置
    const startTime = clock.startTime
    const totalSeconds = Cesium.JulianDate.secondsDifference(currentTime, startTime)
    timeSliderValue.value = Math.min(86400, Math.max(0, totalSeconds))
  })

  //  确保动画默认启用
  viewer.clock.shouldAnimate = true
  viewer.clock.multiplier = playbackSpeed.value
}
// 清空viewer
const clearViewer = () => {
  viewer.entities.removeAll()
  store.closeSatPanel()
}
const taskLong = ref<number>()
const taskLat = ref<number>()
// 标注战场
const markBattle = (battleName: string, lon: number, lat: number) => {
  taskLong.value = lon
  taskLat.value = lat
  viewer.entities.add({
    name: battleName,
    position: Cesium.Cartesian3.fromDegrees(lon, lat, 0),
    // --- 小旗子 ---
    billboard: {
      image: '/img/flag.svg',
      scale: 0.1,
      verticalOrigin: Cesium.VerticalOrigin.CENTER, // 图标底部贴地
      heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
    },
    // --- 名称标签 ---
    label: {
      text: battleName,
      font: '12px sans-serif',
      fillColor: Cesium.Color.WHITE,
      outlineColor: Cesium.Color.YELLOW,
      outlineWidth: 2,
      style: Cesium.LabelStyle.FILL_AND_OUTLINE,
      verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // 文字在图标上方
      pixelOffset: new Cesium.Cartesian2(0, 30), // 向下偏移 50 像素，避免压盖
    },
  })

  // 4. 飞过去看一眼
  viewer.camera.flyTo({
    destination: Cesium.Cartesian3.fromDegrees(lon, lat, 1500000), // 1.5 km 高
    orientation: { heading: 0, pitch: -Cesium.Math.PI_OVER_TWO, roll: 0 },
    duration: 2,
  })
}
//所有卫星实体
let satelliteEntities = new Map<number, Cesium.Entity>()

// 存储每个卫星的多周期轨道数据
const satelliteOrbitData = new Map()

// 时间控制变量
const isPlaying = ref(true)
const playbackSpeed = ref(10.0)
const timeSliderValue = ref(43200) // 默认中午12点（秒）
const currentTimeDisplay = ref('2024-01-01 12:00:00 UTC')
// 时间控制函数
const togglePlayPause = () => {
  isPlaying.value = !isPlaying.value
  viewer.clock.shouldAnimate = isPlaying.value
  console.log('播放状态:', isPlaying.value ? '播放' : '暂停')
}
// 时间轴后退
const rewindTime = () => {
  const currentTime = viewer.clock.currentTime
  const newTime = Cesium.JulianDate.addSeconds(currentTime, -10, new Cesium.JulianDate())
  viewer.clock.currentTime = newTime
}
// 时间轴减速
const decreaseSpeed = () => {
  playbackSpeed.value = Math.max(0.1, playbackSpeed.value / 2)
  viewer.clock.multiplier = playbackSpeed.value
}
//时间轴加速
const increaseSpeed = () => {
  playbackSpeed.value = Math.min(100, playbackSpeed.value * 2)
  viewer.clock.multiplier = playbackSpeed.value
}
//时间轴前进
const forwardTime = () => {
  const currentTime = viewer.clock.currentTime
  const newTime = Cesium.JulianDate.addSeconds(currentTime, 10, new Cesium.JulianDate())
  viewer.clock.currentTime = newTime
}

/**
 * 添加卫星实体
 * @param satellite
 */
const addSatellite = (satellite: SatelliteInfo) => {
  if (!viewer) return
  // 创建卫星位置
  const position = Cesium.Cartesian3.fromDegrees(
    satellite.satellitePosition.longitude,
    satellite.satellitePosition.latitude,
    satellite.satellitePosition.altitude * 1000 // 转换为米
  )

  // 创建卫星实体
  const entity = viewer.entities.add({
    id: `satellite-${satellite.norad}`,
    name: satellite.name_en,
    position: position,
    point: {
      pixelSize: 8,
      color: getSatelliteColor(satellite.sat_type),
      outlineColor: Cesium.Color.WHITE,
      outlineWidth: 2,
      heightReference: Cesium.HeightReference.NONE,
    },
    label: {
      text: satellite.name_en,
      font: '12px sans-serif',
      fillColor: Cesium.Color.WHITE,
      outlineColor: Cesium.Color.BLACK,
      outlineWidth: 2,
      style: Cesium.LabelStyle.FILL_AND_OUTLINE,
      pixelOffset: new Cesium.Cartesian2(0, -20),
      showBackground: true,
      backgroundColor: new Cesium.Color(0, 0, 0, 0.3),
      show: new Cesium.CallbackProperty(() => showLabels.value, false), // 标签的可见性
      // distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 5000000),
    },
  })

  // 保存实体引用
  satelliteEntities.set(satellite.norad, entity)

  return entity
}
const closePanel = () => {
  store.closeSatPanel() // 点到空白也关闭
  showPaths.value = false
  for (const element of satelliteEntities.values()) {
    if (element.path) element.path.show = new Cesium.CallbackProperty(() => false, false)
  }
  lookBattle()
  viewer.trackedEntity = undefined
}
// 监听鼠标左键点击事件并处理实体选择
function listenClickEvents() {
  viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK)
  viewer.screenSpaceEventHandler.setInputAction(async function (event: Cesium.ScreenSpaceEventHandler.PositionedEvent) {
    const picked = viewer.scene.pick(event.position)
    if (!Cesium.defined(picked)) {
      store.closeSatPanel() // 点到空白也关闭
      showPaths.value = false
      for (const element of satelliteEntities.values()) {
        if (element.path) element.path.show = new Cesium.CallbackProperty(() => false, false)
      }
      lookBattle()
      viewer.trackedEntity = undefined
      return
    }
    const entity = picked.id
    if (!entity || !entity.id.startsWith('satellite-')) return
    const noradId = entity.id.split('satellite-')[1]
    const res = await getSatelliteDetail({ norad: Number(noradId) })
    if (res.code === 200) {
      const satellite = res.data
      if (satellite) {
        store.setSelectedSatellite(satellite)
        store.showSatelliteMsgBox = true
        for (const element of satelliteEntities.values()) {
          if (element.path) element.path.show = new Cesium.CallbackProperty(() => false, false)
        }
        const sate = entity as Cesium.Entity
        if (sate && sate.path) {
          showPaths.value = true
          sate.path.show = new Cesium.CallbackProperty(() => showPaths.value, false)
          if (trackEntity.value) {
            // 让相机跟随卫星
            viewer.trackedEntity = sate
          }
        }
      }
    }
  }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
}

const getSatelliteColor = (type: string) => {
  if (type) {
    if (type.includes('军事')) {
      return Cesium.Color.CHARTREUSE
    }
    if (type.includes('气象')) {
      return Cesium.Color.BLUEVIOLET
    }
    if (type.includes('海洋')) {
      return Cesium.Color.BROWN
    }
    if (type.includes('测绘')) {
      return Cesium.Color.BURLYWOOD
    }
    if (type.includes('通信')) {
      return Cesium.Color.BLUE
    }
    if (type.includes('导航')) {
      return Cesium.Color.GREEN
    }
    if (type.includes('侦察')) {
      return Cesium.Color.RED
    }
    if (type.includes('探测')) {
      return Cesium.Color.CHOCOLATE
    }
    if (type.includes('科学')) {
      return Cesium.Color.PURPLE
    }
  }
  return Cesium.Color.ROYALBLUE
}

const renderSateliiteOfTask = async (
  taskId: number,
  filter: { sateType: string; country: string; orbitType: string; orbitStatus: string; payloadStatus: string }
) => {
  if (!viewer) return
  if (taskId) {
    const res = await getTLEDataByTaskId(taskId)
    if (res.code === 200) {
      let satelliteList = res.data.results
      if (filter.sateType !== '全部') {
        satelliteList = satelliteList.filter((s) => s.sat_type.includes(filter.sateType))
      }
      if (filter.country !== '全部') {
        satelliteList = satelliteList.filter((s) => s.country.includes(filter.country))
      }
      if (filter.orbitType !== '全部') {
        satelliteList = satelliteList.filter((s) => s.orbit_type === getOrbitNumType(filter.orbitType))
      }
      if (filter.orbitStatus !== '全部') {
        satelliteList = satelliteList.filter((s) => s.orbit_status === getOrbitNumStatus(filter.orbitStatus))
      }
      if (filter.payloadStatus !== '全部') {
        satelliteList = satelliteList.filter((s) => s.payload_status === getPayloadNumStatus(filter.payloadStatus))
      }
      let norads: string[] = []
      if (satelliteList) {
        norads = satelliteList.map((s) => s.norad_id)
        // 获取TLE真实数据
        const tleDataRes = await getSatelliteTLEData({ norads })
        if (tleDataRes.code === 200) {
          for (let index = 0; index < satelliteList.length; index++) {
            const satel = satelliteList[index]
            if (!satel) {
              continue
            } else {
              //检测satellite.js库是否可用
              if (!satellitejs) {
                continue
              }
              const { name_en, norad_id, sat_type, orbit_type } = satel

              let tleData = tleDataRes.data.find((s) => s.noradId === Number(norad_id))?.satelliteTleResp

              // 缺少TLE数据
              if (!tleData || !tleData.line1 || !tleData.line2) {
                continue
              }
              const satrec = satellitejs.twoline2satrec(tleData.line1, tleData.line2)
              // TLE数据解析失败
              if (!satrec) {
                continue
              }

              // cesium已加载完成(显示时间轴)
              cesiumInitialized.value = true

              // 生成多个周期的轨道数据，支持周期小于一天的卫星持续显示
              const positionProperty = new Cesium.SampledPositionProperty()
              const orbitSamples = []
              const startTime = viewer.clock.currentTime
              // 2分钟步长（原来1分钟），大幅减少采样点数量
              const timeStep = 120
              //低轨90分钟 中轨12小时 其他（高轨|大椭圆）24小时
              const singleOrbitPeriod = orbit_type === 1 ? 90 * 60 : orbit_type === 2 ? 12 * 3600 : 24 * 3600

              // 计算需要生成多少个完整周期来覆盖24小时（最小2个周期）
              const totalPeriods = Math.max(2, Math.ceil((24 * 3600) / singleOrbitPeriod))
              // 生成轨道模拟数据
              for (let period = 0; period < totalPeriods; period++) {
                const periodStartTime = Cesium.JulianDate.addSeconds(
                  startTime,
                  period * singleOrbitPeriod,
                  new Cesium.JulianDate()
                )
                for (let i = 0; i <= singleOrbitPeriod; i += timeStep) {
                  const time = Cesium.JulianDate.addSeconds(periodStartTime, i, new Cesium.JulianDate())
                  try {
                    const positionAndVelocity = satellitejs.propagate(satrec, Cesium.JulianDate.toDate(time))
                    if (positionAndVelocity && positionAndVelocity.position) {
                      const positionEci = positionAndVelocity.position

                      // 简化的ECI到ECEF转换（使用地球自转近似）
                      const gmst = satellitejs.gstime(Cesium.JulianDate.toDate(time))
                      const positionEcf = satellitejs.eciToEcf(positionEci, gmst)

                      if (positionEcf) {
                        orbitSamples.push({
                          time: time,
                          position: new Cesium.Cartesian3(
                            positionEcf.x * 1000, // 转换为米
                            positionEcf.y * 1000,
                            positionEcf.z * 1000
                          ),
                          period: period, // 记录周期编号
                        })
                        positionProperty.addSample(
                          time,
                          new Cesium.Cartesian3(
                            positionEcf.x * 1000, // 转换为米
                            positionEcf.y * 1000,
                            positionEcf.z * 1000
                          )
                        )
                      }
                    }
                  } catch (error) {
                    console.log(error)
                  }
                }
              }
              // 轨道数据生成失败
              if (orbitSamples.length === 0) {
                continue
              }
              // 存储轨道数据用于时间-based周期选择
              satelliteOrbitData.set(Number(norad_id), {
                samples: orbitSamples,
                singleOrbitPeriod: singleOrbitPeriod,
                totalPeriods: totalPeriods,
                startTime: startTime,
              })
              // 检查实体是否已存在
              const existingEntity = viewer.entities.getById(`satellite-${norad_id}`)
              if (existingEntity) {
                continue
              }
              // 创建卫星实体
              const satelliteEntity = viewer.entities.add({
                id: `satellite-${norad_id}`,
                name: name_en,
                availability: new Cesium.TimeIntervalCollection([
                  new Cesium.TimeInterval({ start: viewer.clock.startTime, stop: viewer.clock.stopTime }), // 可用时间区间
                ]),
                description: '',
                position: positionProperty,
                show: true, // 默认显示，后续通过筛选控制可见性
                point: {
                  pixelSize: 8,
                  color: getSatelliteColor(sat_type),
                  outlineColor: Cesium.Color.WHITE,
                  outlineWidth: 1,
                  heightReference: Cesium.HeightReference.NONE,
                  show: true, // 点的可见性
                },
                label: {
                  text: name_en,
                  font: '12px sans-serif',
                  fillColor: Cesium.Color.WHITE,
                  outlineColor: Cesium.Color.BLACK,
                  outlineWidth: 2,
                  style: Cesium.LabelStyle.FILL_AND_OUTLINE,
                  pixelOffset: new Cesium.Cartesian2(0, -20),
                  showBackground: true,
                  backgroundColor: new Cesium.Color(0, 0, 0, 0.3),
                  // distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 5000000),
                  show: new Cesium.CallbackProperty(() => showLabels.value, false), // 标签的可见性
                },
                // 卫星轨迹线
                path: {
                  show: new Cesium.CallbackProperty(() => showPaths.value, false),
                  leadTime: singleOrbitPeriod * 2,
                  trailTime: 0,
                  width: 1,
                  material: new Cesium.PolylineGlowMaterialProperty({
                    glowPower: 0.2, // 发光强度
                    color: Cesium.Color.YELLOW, // 黄色轨迹
                  }),
                },
              })

              satelliteEntities.set(Number(norad_id), satelliteEntity)
            }
          }
        }
      }
      lookBattle()
    }
  }
}
function lookBattle() {
  if (taskLong.value && taskLat.value) {
    viewer.camera.flyTo({
      destination: Cesium.Cartesian3.fromDegrees(taskLong.value, taskLat.value, 25000000),
      orientation: { heading: 0, pitch: -Cesium.Math.PI_OVER_TWO, roll: 0 },
      duration: 2,
    })
  }
}
defineExpose({ addSatellite, clearViewer, markBattle, renderSateliiteOfTask })
onMounted(() => {
  initViewer()
})
</script>
<style lang="scss" scoped>
.cesium-container {
  height: 100%;
  /* 1. 进入前：藏在左边 */
  .slide-enter-from {
    transform: translateX(100%);
  }
  /* 2. 进入过程 & 离开过程：做动画 */
  .slide-enter-active,
  .slide-leave-active {
    transition: transform 0.5s ease-in-out;
  }
  /* 3. 离开后：再滑回去 */
  .slide-leave-to {
    transform: translateX(100%);
  }
  .credit {
    display: none;
  }
  .toolbox {
    padding: 0 5px;
    height: 30px;
    z-index: 1;
    position: absolute;
    top: 0;
    left: 0;
    display: flex;
    gap: 5px;
    width: 100%;
    background: rgba($color: #000000, $alpha: 0.8);
  }
  .timeline-panel {
    background: rgba($color: #000000, $alpha: 0.8);
    z-index: 1;
    position: absolute;
    bottom: 10px;
    left: 50%;
    transform: translate(-50%, 0);
    padding: 10px;
    border-radius: 5px;
    .timeline-controls {
      display: flex;
      gap: 2px;
      justify-content: center;
    }
  }
  .speed-panel {
    display: none;
  }
  .sat-panel {
    position: absolute;
    top: 10px;
    right: 10px;
    background: rgba(19, 19, 19, 0.9);
    padding: 12px;
    border-radius: 4px;
    font-size: 14px;
    pointer-events: auto;
    z-index: 999;
    width: 320px;
    max-height: 600px;
    overflow-y: hidden;
    .close-btn {
      float: right;
      cursor: pointer;
      margin-left: 8px;
    }
    .sat-Content {
      & > div {
        text-align: left;
        color: #dfdfdf;
        padding: 2px;
      }
      & > div:first-child {
        display: flex;
        justify-content: space-between;
      }
      .desc {
        font-size: 12px;
        line-height: 20px;
      }
    }
  }
}
</style>
